package user;

import java.util.ArrayList;
import java.util.TreeMap;

public class UsersList {
	
	private TreeMap <String, User> users = null ;
	private ArrayList <UsersListObserver> observers = null ;
	
	public UsersList () {
		this.users = new TreeMap <String, User> () ;
		this.observers = new ArrayList <UsersListObserver> () ;
	}
	
	/**
	 * Add a new Observer that will be notify on any update
	 * 
	 * @param ulo
	 */
	public UsersListObserver addObserver (UsersListObserver ulo) {
		this.observers.add(ulo) ;
		return ulo ;
	}
	
	/**
	 * Remove an Observer from the list
	 * 
	 * @param ulo
	 */
	public UsersListObserver removeObserver (UsersListObserver ulo) {
		this.observers.remove(ulo) ;
		return ulo ;
	}
	
	/**
	 * Add the specified user to the list if he is not already in,
	 * update the information otherwise.
	 * 
	 * @param user The user to add or update
	 */
	public void addOrUpdate (User user) {
		if (this.users.containsKey(user.getIdentifier())) {
			if (!user.getUsername().equals(this.users.get(user.getIdentifier()).getUsername())) { 
				/* Create a copy of the old user, necessary for fireUpdateUser. */
				User oldUser = new User(this.users.get(user.getIdentifier())) ;
				this.users.put(user.getIdentifier(), user) ;
				for (UsersListObserver ulo : this.observers) {
					ulo.fireUpdateUser(oldUser, this.users.get(user.getIdentifier())) ;
				}
			}
		}
		else {
			this.users.put(user.getIdentifier(), user) ;
			for (UsersListObserver ulo : this.observers) {
				ulo.fireNewUser(user) ;
			}
		}
	}
	
	/**
	 * @param identifier The unique ID of the user
	 * @return true if there is a user connected with this hostname.
	 */
	public boolean isConnected (String identifier) {
		return  this.users.containsKey(identifier);
	}
	
	/**
	 * Delete the user corresponding to the specified hostname.
	 * 
	 * @param hostAddr
	 */
	public void delete (String identifier) {
		if (isConnected(identifier)) {
			User ude = this.users.remove(identifier) ;
			for (UsersListObserver ulo : this.observers) {
				ulo.fireDeleteUser(ude) ;
			}
		}
	}
	
	/**
	 * Remove all user from the list.
	 */
	public synchronized void removeAll () {
		for (String identifier : this.users.keySet()) {
			User ude = this.users.get(identifier) ;
			for (UsersListObserver ulo : this.observers) {
				ulo.fireDeleteUser(ude) ;
			}
		}
		this.users = new TreeMap <String, User> () ;
	}
	
	/**
	 * @param identifier A unique identifier for this user
	 * @return The user corresponding to the identifier, null if there is no user corresponding.
	 */
	public User get (String identifier) {
		return this.users.get(identifier) ;
	}

}
